/// <reference path="./jquery-1.8.2.min.js" />

var util = {};

function Point2D(x, y) {
	this.x = x;
	this.y = y;
}

function Point3D(x, y, z) {
	this.x = x;
	this.y = y;
	this.z = z;
}

function Rectangle() {
	this.x = 0;
	this.y = 0;
	this.w = 0;
	this.h = 0;
	
	if (arguments.length == 4) {
		this.x = arguments[0];
		this.y = arguments[1];
		this.w = arguments[2];
		this.h = arguments[3];
	} else if (arguments.length == 2) {
		var p = arguments[0];
		var s = arguments[1];
		if (s.w != null && p.x != null) {
			this.x = p.x;
			this.y = p.y;
			this.w = s.w;
			this.h = s.h;
		}
	}
	
	this.setSize = function (s) {
		this.w = s.w;
		this.h = s.h;
	};
	
	this.getSize = function () {
		return new Size(this.w, this.h);
	};
	
	this.setLocation = function (l) {
		this.x = l.x;
		this.y = l.y;
	};
	
	this.getLocation = function () {
		return new Point2D(this.x, this.y);
	};
	
	this.getBottom = function () {
		return this.y - this.h;
	};
	
	this.getRight = function () {
		return this.w + this.x;
	};
	
	this.contains = function () {
		if (arguments.length == 1) {
			var o = arguments[0];
			if (o.constructor == Point2D) {
				if ((o.x < this.x) || (o.x > this.getRight()) ||
					(o.y > this.y) || (o.y < this.getBottom())) {
					return false;
				}
				return true;
			} else if (o.constructor == Rectangle) {
				if ((o.x >= this.x) && (o.getRight() <= this.getRight()) &&
					(o.y <= this.y) && (o.getBottom() >= this.getBottom())) {
					return true;
				}
			}
		}
		return false;
	};
	
	this.intersects = function () {
		if (arguments.length == 1) {
			var o = arguments[0];
			if (o.constructor == Rectangle) {
				if ((o.getRight() >= this.x) && (o.x <= this.getRight()) &&
					(o.getBottom() <= this.y) && (o.y >= this.getBottom()) ) {
					return true;
				}
			}
		}
		return false;
	};
}

function Coordinates2D() {
	this.x = 0;
	this.y = 0;
	this.angleFromCamera = 0;
	
	this.getPoint = function() {
		return new Point2D(this.x, this.y);
	};
	
	this.getAngleFromCameraDegrees = function() {
		return util.degrees(this.angleFromCamera);
	};
	
	this.copyInto = function(c) {
		c.x = this.x;
		c.y = this.y;
		c.angleFromCamera = this.angleFromCamera;
		c.update();
	};
	
	this.update = function() {};
}

function Coordinates3D() {
	this.z = 0;
	
	this.getPoint3D = function() {
		return new Point3D(this.x, this.y, this.z);
	};
	
	this.copyInto = function(c) {
		c.x = this.x;
		c.y = this.y;
		c.z = this.z;
		c.angleFromCamera = this.angleFromCamera;
		c.update();
	};
}
Coordinates3D.prototype = new Coordinates2D();

function Placement() {
	this.h = 0;
	this.w = 0;
	this.bearing = 0;
	this.totalMovement = 0;
	
	this.getBearingDegrees = function() {
		return util.degrees(this.bearing);
	};
	
	this.getRectangle = function() {
		return new Rectangle(this.x, this.y, this.w, this.h);
	};

	this.move = function(distance)
	{
		this.x += distance * Math.cos(this.bearing);
		this.y += distance * Math.sin(this.bearing);
		this.totalMovement += distance;
	};

	this.sideStep = function(distance)
	{
		if (distance < 0)
		{
			this.x += distance * Math.cos(this.bearing + util._270);
			this.y += distance * Math.sin(this.bearing + util._270);
		}
		else if (distance > 0)
		{
			this.x += distance * Math.cos(this.bearing - util._90);
			this.y += distance * Math.sin(this.bearing - util._90);
		}
	};

	this.turn = function(radians)
	{
		this.bearing += radians;
		while (this.bearing < 0) this.bearing = this.bearing + util._360;
		if (this.bearing >= util._360) this.bearing = (this.bearing % util._360);
	};
	
	this.copyInto = function(c) {
		c.x = this.x;
		c.y = this.y;
		c.z = this.z;
		c.h = this.h;
		c.w = this.w;
		c.bearing = this.bearing;
		c.totalMovement = this.totalMovement;
		c.angleFromCamera = this.angleFromCamera;
		c.update();
	};
}
Placement.prototype = new Coordinates3D();


function PointViewLocation()
{
	this.placement = new Placement();
	this.distance = 0.0;
	this.distance3D = 0.0;
	this.isVisible = true;
	this.point = new Point2D(0,0);
	this.shadowPoint = new Point2D(0,0);
}

function ObjectViewLocation()
{
    this.point = new Point2D(0, 0);
    this.shadowPoint = new Point2D(0, 0);
    this.objectRectangle = new Rectangle();
    this.collisionRectangle = new Rectangle();
    this.shadowRectangle = new Rectangle();
}
ObjectViewLocation.prototype = new PointViewLocation();


function GameObject() {
    this.locationRelativeToCamera = null;
	this.objectId = 0;
	this.speed = 0.0;
	this.frameIndex = 0;
	this.color = null;
	this.objectName = null;
	this.painter = null;
	this.path = [];
	this.name = "unnamed";
	
	this.updateLocation = function (context) {
	    this.locationRelativeToCamera = util.calculateObjectViewLocation(this.locationRelativeToCamera, context.camera, context.viewPort, this);
	};
	
	this.tick = function() {};
}
GameObject.prototype = new Placement();


function Size(width, height) {
	this.w = width;
	this.h = height;
}

function ViewPort(unitWidth, horizontalViewableAngle, verticalViewableAngle) {
	this.unitHeight = 3;
	this.unitWidth = (unitWidth == null ? 6 : unitWidth);
	this.scale = null;
	this.size = new Size(200, 100);
	this.distanceToView = null;
	this.horizontalViewableAngle = horizontalViewableAngle;
	this.verticalViewableAngle = verticalViewableAngle;
	
	this.getWidthOfView = function (width) {
		this.unitWidth = width;
		this.recalculate();
	};
	
	this.setHeightOfView = function (height) {
		this.unitHeight = height;
		this.recalculate(true);
	};
	
	this.setHorizontalViewableAngle = function (angle) {
		this.horizontalViewableAngle = angle;
		this.recalculate();
	};
	
	this.setVerticalViewableAngle = function (angle) {
		this.verticalViewableAngle = angle;
		this.recalculate(true);
	};
	
	this.isInView = function (angle) {
		return true;
	};
	
	this.getScale = function () {
		return this.size.w / this.unitWidth;
	};
	
	this.setPixelSize = function () {
		if (arguments.length == 1){
			this.size.w = arguments[0].w;
			this.size.h = arguments[0].h;
		}
		else if (arguments.length == 2) {
			this.size.w = arguments[0];
			this.size.h = arguments[1];
		}
		this.recalculate();
	};
	
	this.recalculate = function (useHeight) {
		if (useHeight == null)
			useHeight = false;
		
		if (useHeight) {
			this.scale = this.size.h / this.unitHeight;
			this.unitWidth = this.size.w / this.scale;
			this.distanceToView = (this.unitHeight / 2.0) / Math.atan(this.verticalViewableAngle);
		} else {
			this.scale = this.size.w / this.unitWidth;
			this.unitHeight = this.size.h / this.scale;
			this.distanceToView = (this.unitWidth / 2.0) / Math.atan(this.horizontalViewableAngle);
		}
	};
	
	this.recalculate();
}

function SpriteSheet(img, columns, rows) {
	//var img = new Image(imagePath);
	this.height = img.height;
	this.width = img.width;
	this.image = img;
	this.columns = columns;
	this.rows = rows;
	this.sl_w = this.width / columns;
	this.sl_w = this.width / columns;
	this.sl_h = this.height / rows;
	this.col = 0;
	this.row = 0;
	this.direction = 'f';
	this.col_d = 1;
	this.transparentColor = 0;
	this.sizeMultiplier = 1.0;
	this.spriteState = 0;
	
	this.rotate = function (x) {
		if (isNaN(x))
			this.setDirection(x);
		else {
			var r = ['f', 'r', 'b', 'l'];
			var i = r.indexOf(this.direction) + x;
			if (i < 0)
				i = 3;
			i = i % 4;
			this.setDirection(r[i]);
		}
	};
	
	this.setDirection = function (dir) {
		this.direction = dir;
		switch (dir) {
		case 'f':
			this.row = 0;
			break;
		case 'l':
			this.row = 1;
			break;
		case 'r':
			this.row = 2;
			break;
		case 'b':
			this.row = 3;
			break;
		}
	};
	
	this.getFrameCount = function () {
		return (this.spriteState == 0) ? 1 : 3;
	};
	
	this.getXOff = function () {
		return this.sl_w * this.col;
	};
	
	this.getYOff = function () {
		return this.sl_h * this.row;
	};
	
	this.tick = function () {
		if (this.col >= (this.columns - 1))
			this.col_d = -1;
		else if (this.col <= 0)
			this.col_d = 1;
		this.col += this.col_d;
	};
	
	this.draw = function (ctx, doClear) {
		ctx.drawImage(this.image,
			this.getXOff(), this.getYOff(), this.sl_w, this.sl_h,
			10, 10, this.sl_w * this.sizeMultiplier, this.sl_h * this.sizeMultiplier);
	};
}


function PaintingContext() {
	this.camera = null;
	this.frontLayer = null;
	this.backLayer = null;
	this.gameObject = null;
	this.viewPort = null;
}

function Utility() {

	this.DEG2RAD = Math.PI / 180.0;
	this.RAD2DEG = 180.0 / Math.PI;
	this.origin2D = new Coordinates2D();
	this.origin3D = new Coordinates3D();
	this.placementRule = "2D-Flat"; // 2D, 3D, and 2D-Flat (default)
	
	this.random = function (a, b) {
	    if (a == null) return Math.random();
	    else if (b == null) return Math.round(Math.random() * a);
	    else return Math.round((Math.random() * (b-a)) + a);
	};

	this.radians = function (degrees) {
		return degrees * this.DEG2RAD;
	};
	
	this.degrees = function (radians) {
		return radians * this.RAD2DEG;
	};
	
	this._45 = this.radians(45);
	this._90 = this.radians(90);
	this._135 = this.radians(135);
	this._180 = this.radians(180);
	this._225 = this.radians(225);
	this._270 = this.radians(270);
	this._315 = this.radians(315);
	this._360 = this.radians(360);
	
	this.determine4WayDirection = function(angle) {
		var a = angle > util._360 ? (angle % this._360) : angle;
		
		if ((a >= 0 && a < Math.PI / 4.0) || (a >= this._315 && a <= (Math.PI * 2.0)))
			return 'b';
		else if (a >= this._45 && a < this._135)
			return 'l';
		else if (a >= this._135 && a < this._225)
			return 'f';
		else
			return 'r';
	};
	
	this.orderByDistance = function (gameObjects) {
	    gameObjects.sort(function(a, b) {
	        var da = a.locationRelativeToCamera.distance;
	        var db = b.locationRelativeToCamera.distance;
	        return ((da > db) ? -1 : ((da < db) ? 1 : 0));
	    });
	};

    //double AngleToPoint(this Coordinates3D first, Coordinates3D toPoint)
	this.angleToPoint = function(first, toPoint) {
		return Math.atan2(toPoint.y - first.y, toPoint.x - first.x);
	};
	
	//double FindDistance2D(ICoordinates2D a, ICoordinates2D b)
	this.findDistance2D = function(a, b) {
		return Math.sqrt(Math.pow((a.x - b.x), 2) + Math.pow((a.y - b.y), 2));
	};
	
	//double FindDistance3D(ICoordinates3D a, ICoordinates3D b)
	this.findDistance3D = function(a, b) {
		var longLeg = this.findDistance2D(a, b),
			shortLeg = Math.abs(a.z - b.z),
			hypotenuse = shortLeg === 0 ? longLeg : Math.sqrt(Math.pow(longLeg, 2) + Math.pow(shortLeg, 2));

		return hypotenuse;
	};
	
	//public static double? GetAngle(ICoordinates2D c1, ICoordinates2D c2)
	this.getAngle = function(c1, c2) {
		var angle = null;
		if (c1.x != c2.x || c1.y != c2.y)
		{
			angle = Math.atan((c1.x - c2.x) / (c1.y - c2.y));
		}
		return angle;
	};
	
	//bool ClipPolygonOnYAxis(List<IPlacement> polygon, double xShift = 0)
	this.clipPolygonOnYAxis = function(polygon, xShift) {};
	
	//IPlacement origin, ICoordinates3D coordinates, ref IPlacement relativePlacement
	this.findRelativeLocation3D = function(origin, coordinates, relativePlacement) {
		if (relativePlacement == null) relativePlacement = new Placement();
		coordinates.copyInto(relativePlacement);
		
		var relativeAngleToX, relativeAngle,
			translatedX = (coordinates.x - origin.x),
			translatedY = (coordinates.y - origin.y),
            reverseBearing = origin.bearing; // I don't know why this works here and not in the windows app - I will have to investigate!
			//reverseBearing = -1*origin.bearing;


		relativePlacement.x = (Math.cos(reverseBearing) * translatedX) - (Math.sin(reverseBearing) * translatedY);
		relativePlacement.y = (Math.sin(reverseBearing) * translatedX) + (Math.cos(reverseBearing) * translatedY);

		relativeAngleToX = Math.atan2(Math.abs(relativePlacement.y), Math.abs(relativePlacement.x)) *
			(relativePlacement.y < 0 && relativePlacement.x > 0 ? -1.0 : 1.0);

		if (relativePlacement.x < 0 && relativePlacement.y < 0) relativeAngle = Math.abs(relativeAngleToX) + Math.PI;
		else if (relativePlacement.x > 0 && relativePlacement.y < 0) relativeAngle = 2.0 * Math.PI - Math.abs(relativeAngleToX);
		else if (relativePlacement.x < 0 && relativePlacement.y > 0) relativeAngle = Math.PI - Math.abs(relativeAngleToX);
		else relativeAngle = relativeAngleToX;

		relativePlacement.angleFromCamera = relativeAngle;
		if (relativePlacement.angleFromCamera < 0) relativePlacement.angleFromCamera = this._360 + relativePlacement.angleFromCamera;
		relativePlacement.angleFromCamera = relativePlacement.angleFromCamera > this._360 ? (this._360 % relativePlacement.angleFromCamera) : relativePlacement.angleFromCamera;
		
		return relativePlacement;
	};
	
	//IPlacement origin, IPlacement objectLocation, ref IPlacement relativePlacement
	this.findRelativeLocation = function(origin, objectLocation, relativePlacement) {
		relativePlacement = this.findRelativeLocation3D(origin, objectLocation, relativePlacement);

		relativePlacement.bearing = objectLocation.bearing - origin.bearing;
		if (relativePlacement.bearing < 0) relativePlacement.bearing = this._360 + relativePlacement.bearing;
		relativePlacement.bearing = relativePlacement.bearing > this._360 ? (this._360 % relativePlacement.bearing) : relativePlacement.bearing;
		
		return relativePlacement;
	};
	
	this.__calculateViewLocationCore = function(viewLocation, camera, viewPort, location, isPointLocation, calculateIfOffScreen) {
		calculateIfOffScreen = calculateIfOffScreen == null ? false : calculateIfOffScreen;
        viewLocation.isVisible = true;
		try
		{
			var relativeLocation = null
			//TODO: do we need to calculate this every time?
			if (isPointLocation && viewLocation.placement != null) {
				relativeLocation = viewLocation.placement = relativeLocation;
			}
			else {
				relativeLocation = isPointLocation ? this.findRelativeLocation3D(camera, location) : this.findRelativeLocation(camera, location);
				viewLocation.placement = relativeLocation;
			}

			var angle = (relativeLocation.angleFromCamera < this._180) ? relativeLocation.angleFromCamera : this._360 - relativeLocation.angleFromCamera;

			if (relativeLocation.x <= 0.0 ||
				(angle > (viewPort.horizontalViewableAngle / 2.0) + this.radians(2.0)))
			{
				viewLocation.isVisible = true;
			}

			var doCalculations = (viewLocation.isVisible || (calculateIfOffScreen && relativeLocation.x > 0));
			if (doCalculations)
			{
				// Pick one of the three above.
				var unitDistance = 0,
					top = relativeLocation.z + relativeLocation.h,
					bottom = relativeLocation.z,
					cameraHeight = camera.h + camera.z;

				var org = new Coordinates3D();
				org.z = cameraHeight;

				var unitDistance3D = this.findDistance3D(org, relativeLocation) * (relativeLocation.x > 0 ? 1 : -1);
				switch (this.placementRule)
				{
					case "2D":
					    unitDistance = this.findDistance2D(org, relativeLocation) * (relativeLocation.x > 0 ? 1 : -1);
						break;
					case "3D":
						unitDistance = unitDistance3D;
						break;
					default:
						unitDistance = relativeLocation.x;
						break;
				}

				if (unitDistance < viewPort.distanceToView)
					viewLocation.isVisible = false;
				else
				{
					viewLocation.distance = unitDistance;
					viewLocation.distance3D = unitDistance3D;
					var pointOffsetFromHorizon_Ground = (cameraHeight / unitDistance) * viewPort.distanceToView;
					var pointOffsetFromHorizon_Bottom = (Math.abs(bottom - cameraHeight) / unitDistance) * viewPort.distanceToView;
					var pointOffsetFromHorizon_Top = (Math.abs(top - cameraHeight) / unitDistance) * viewPort.distanceToView;

					var pointOffsetFromVerticalHorizon = (relativeLocation.y / unitDistance) * viewPort.distanceToView;

					// Shadow
					var unitShadowHeight = Math.abs(((cameraHeight / (unitDistance + relativeLocation.w)) * viewPort.distanceToView) - pointOffsetFromHorizon_Ground);

					pointOffsetFromHorizon_Ground = (cameraHeight - pointOffsetFromHorizon_Ground);

					pointOffsetFromHorizon_Bottom = (bottom > cameraHeight)
						? (cameraHeight + pointOffsetFromHorizon_Bottom) : (cameraHeight - pointOffsetFromHorizon_Bottom);

					pointOffsetFromHorizon_Top = (top > cameraHeight)
						? (cameraHeight + pointOffsetFromHorizon_Top) : (cameraHeight - pointOffsetFromHorizon_Top);

				    //var horizontalOffset = Math.round(pointOffsetFromVerticalHorizon * viewPort.scale) * (relativeLocation.bearing >= 0 ? -1 : 1);
					var horizontalOffset = Math.round(pointOffsetFromVerticalHorizon * viewPort.scale) * -1;

					// shadow calc
					var shadowHeight = Math.round(unitShadowHeight * viewPort.scale);
					
					if (isPointLocation) {
                        var point = new Point2D();

                        point.y = (viewPort.size.h / 2) + Math.round((cameraHeight - pointOffsetFromHorizon_Top) * viewPort.scale);
                        point.x = (viewPort.size.w / 2) + horizontalOffset;

                        viewLocation.point = point;

                        var shadowPoint = new Point();

                        shadowPoint.y = (viewPort.size.h / 2) + Math.round((cameraHeight - pointOffsetFromHorizon_Ground) * viewPort.scale);
                        shadowPoint.x = point.x;


                        viewLocation.shadowPoint = shadowPoint;
					}
					else {
						var objectRectangle = new Rectangle();
						objectRectangle.h = Math.round((pointOffsetFromHorizon_Top - pointOffsetFromHorizon_Bottom) * viewPort.scale);
						if (location.h > 0) objectRectangle.w = Math.round((location.w * objectRectangle.h) / location.h);
						else objectRectangle.w = 0;
						objectRectangle.y = (viewPort.size.h / 2) + Math.round((cameraHeight - pointOffsetFromHorizon_Top) * viewPort.scale);
						objectRectangle.x = (viewPort.size.w / 2) - (objectRectangle.w / 2) + horizontalOffset;

						var shadowRectangle = new Rectangle();
						shadowRectangle.h = shadowHeight;
						shadowRectangle.w = objectRectangle.w;
						shadowRectangle.x = objectRectangle.x;
						shadowRectangle.y = (viewPort.size.h / 2) + Math.round((cameraHeight - pointOffsetFromHorizon_Ground) * viewPort.scale) - (shadowHeight / 2);

						viewLocation.objectRectangle = objectRectangle;
						viewLocation.shadowRectangle = shadowRectangle;
					}
				}
			}
		}
		catch (err)
		{
			alert(""+err.number + " - " + err.description);
		}
		return viewLocation;
	};

	this.toECEF = function (lat, lon) {

	    var cosLat = Math.cos(this.radians(lat)),
	        sinLat = Math.sin(this.radians(lat)),
	        cosLon = Math.cos(this.radians(lon)),
	        sinLon = Math.sin(this.radians(lon)),
            rad = 6378137.0,
	        f = 1.0 / 298.257224,
            h = 0.0,
            C = 1.0 / Math.sqrt(cosLat * cosLat + (1.0 - f) * (1.0 - f) * sinLat * sinLat),
            S = (1.0 - f) * (1.0 - f) * C,
            coords = [];
	    coords[0] = (rad * C + h) * cosLat * cosLon; // x
	    coords[1] = (rad * C + h) * cosLat * sinLon; // y
	    coords[2] = (rad * S + h) * sinLat; // z
	    var date = new Date()
	    coords[3] = date.getSeconds();

	    return coords;
	};

	//public static void CalculateObjectViewLocation(ref IObjectViewLocation viewLocation, ICamera camera,
	//		IViewPort viewPort, IPlacement objectLocation, bool calculateIfOffScreen = false)
	this.calculateObjectViewLocation = function(viewLocation, camera, viewPort, objectLocation, calculateIfOffScreen) {
	    return this.__calculateViewLocationCore(viewLocation, camera, viewPort, objectLocation, false, calculateIfOffScreen);
	};
	
	//public static void CalculatePointViewLocation(ref IPointViewLocation viewLocation, ICamera camera,
	//		IViewPort viewPort, ICoordinates3D objectLocation, bool calculateIfOffScreen = false)
	this.calculatePointViewLocation = function(viewLocation, camera, viewPort, objectLocation, calculateIfOffScreen) {
	    return this.__calculateViewLocationCore(viewLocation, camera, viewPort, objectLocation, true, calculateIfOffScreen);
	};
	
	/*	
        public static bool ClipPolygonOnYAxis(List<IPlacement> polygon, double xShift = 0)
        {
            List<IPlacement> fixedPoints = new List<IPlacement>();
            IPlacement point,
            prevPoint = polygon[polygon.Count - 1];
            for (int i = 0; i < polygon.Count; i++)
            {
                point = polygon[i];
                double prevX = prevPoint.X - xShift;
                double currX = point.X - xShift;
                // do check on y...
                if (prevX >= 0)
                {
                    fixedPoints.Add(prevPoint);
                }

                if ((prevX >= 0 && currX < 0) || (prevX < 0 && currX >= 0))
                {
                    // Slope intercept crap: y = mx + b => b = y - mx, m = (y2-y1) / (x2-x1)
                    var yIntercept = point.Y - ((prevPoint.Y - point.Y) / (prevX - currX)) * currX;
                    var zIntercept = point.Z - ((prevPoint.Z - point.Z) / (prevX - currX)) * currX;
                    Placement pnew = new Placement();
                    prevPoint.CopyInto(pnew);
                    pnew.X = xShift;
                    pnew.Y = yIntercept;
                    pnew.Z = zIntercept;
                    fixedPoints.Add(pnew);
                }

                prevPoint = point;
            }
            polygon.Clear();
            polygon.AddRange(fixedPoints);

            return (fixedPoints.Count >= 3);
        }

        /// <summary>
        /// Expands hard points into points based on the movement distance.
        /// </summary>
        public static List<Coordinates3D> ExpandPath(this List<Coordinates3D> path, double interval)
        {
            // Temporary
            int Z = 0;
            List<Coordinates3D> expandedPath = new List<Coordinates3D>();
            for (int i = 0; i < path.Count - 1; i++)
            {
                double angle = path[i].AngleToPoint(path[i + 1]);
                expandedPath.Add(path[i]);

                double distanceBetweenHardPoints = Utility.FindDistance3D(path[i], path[i + 1]);
                for (int j = 0; j < (distanceBetweenHardPoints - interval) / interval; j++)
                {
                    double x = path[i].X + interval * (j + 1) * Math.Cos(angle);
                    double y = path[i].Y + interval * (j + 1) * Math.Sin(angle);

                    // Add new dynamic point.
                    expandedPath.Add(new Coordinates3D(x, y, Z));
                }
            }
            return expandedPath;
        }


        /// <summary>
        /// Creates the rounded rectangle path.
        /// </summary>
        /// <param name="rect">The rect.</param>
        /// <param name="cornerRadius">The corner radius.</param>
        /// <returns></returns>
        public static GraphicsPath CreateRoundedRectanglePath(Rectangle rect, int cornerRadius)
        {
            GraphicsPath roundedRect = new GraphicsPath();
            roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);
            roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y);
            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);
            roundedRect.AddLine(rect.Right, rect.Y + cornerRadius * 2, rect.Right, rect.Y + rect.Height - cornerRadius * 2);

            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);

            roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom);
            roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);
            roundedRect.AddLine(rect.X, rect.Bottom - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2);
            roundedRect.CloseFigure();
            return roundedRect;
        }

        public static Bitmap CreateMask(Bitmap image, Color transparencyColor)
        {
            Bitmap mask = new Bitmap(image.Width, image.Height);
            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    Color pixel = image.GetPixel(x, y);
                    if (pixel.A == transparencyColor.A &&
                        pixel.R == transparencyColor.R &&
                        pixel.G == transparencyColor.G &&
                        pixel.B == transparencyColor.B)
                    {
                        mask.SetPixel(x, y, Color.White);
                    }
                    else
                    {
                        mask.SetPixel(x, y, Color.Black);
                    }
                }
            }
            mask.Save(@"masktest.png", ImageFormat.Png);
            image.Save(@"realimage.png", ImageFormat.Png);
            return mask;
        }

        /// <summary>
        /// Adjusts the brightness matrix.
        /// </summary>
        /// <param name="img">The img.</param>
        /// <param name="value">The value.</param>
        public static void AdjustBrightnessMatrix(Bitmap img, int value)
        {
            if (value == 0) // No change, so just return
                return;

            float sb = (float)value / 255F;
            float[][] colorMatrixElements =
                  {
                        new float[] {1,  0,  0,  0, 0},
                        new float[] {0,  1,  0,  0, 0},
                        new float[] {0,  0,  1,  0, 0},
                        new float[] {0,  0,  0,  1, 0},
                        new float[] {sb, sb, sb, 1, 1}
                                          };

            ColorMatrix cm = new ColorMatrix(colorMatrixElements);
            ImageAttributes imgattr = new ImageAttributes();
            Rectangle rc = new Rectangle(0, 0, img.Width, img.Height);
            Graphics g = Graphics.FromImage(img);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            imgattr.SetColorMatrix(cm);
            g.DrawImage(img, rc, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgattr);

            //Clean everything up
            imgattr.Dispose();
            g.Dispose();

        }
	*/
}

util = new Utility();
